package com.passion.fs.vo;

import cn.hutool.core.lang.UUID;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.passion.common.exception.MyException;
import com.passion.common.util.FileUtil;
import com.passion.fs.entity.FileInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.web.multipart.MultipartFile;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 类描述：文件业务对象
 *
 * @author ZhuYin
 * @since 2025年01月06日
 */
@ApiModel("文件信息VO")
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class FileInfoVO implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 文件存入数据库中的id，也是文件存入文件系统中的名称
     */
    @ApiModelProperty(name = "主键ID")
    private String id;

    /**
     * 父id
     */
    @ApiModelProperty(name = "父级ID")
    private String parentId;

    /**
     * 所在存储桶名称
     */
    @ApiModelProperty(name = "所在存储桶名称")
    private String bucketName;

    /**
     * 原始文件名称
     */
    @ApiModelProperty(name = "文件原始名称")
    private String originalName;

    /**
     * 在文件系统中的名称，id + 后缀名
     */
    @ApiModelProperty(name = "文件系统中的名称，id+后缀名")
    private String fileSysName;

    /**
     * 显示名称
     */
    @ApiModelProperty(name = "显示名称")
    private String showName;

    /** 文件扩展名 */
    @ApiModelProperty(name = "文件扩展名")
    private String fileExt;

    /**
     * 文件类型：bucket-存储桶 dir-目录 imageFile-图片文件 normalOfficeFile-常规office文件 codeFile-代码文件 zipFile-压缩文件 ...
     * 该字段用来给前端做选用文件图标的判断
     */
    @ApiModelProperty(name = "文件类型")
    private String fileType;

    /**
     * 文件大小，单位：字节
     */
    @ApiModelProperty(name = "文件大小，单位:字节")
    private Long fileSize;

    /**
     * 文件md5值
     */
    @ApiModelProperty(name = "文件md5值")
    private String fileMd5;

    /**
     * 目录标识：0-文件 1-目录
     */
    @ApiModelProperty(name = "是否是文件夹：1-是 0-否")
    private Integer dirFlag;

    /**
     * 文件存储的路径
     */
    @ApiModelProperty(name = "文件存储路径")
    private String filePath;

    /** 文件加密串 */
    @ApiModelProperty(name = "文件加密串")
    private String secretKey;

    /**
     * 源文件的访问(下载)路径
     */
    @ApiModelProperty(name = "源文件的访问(下载)路径")
    private String accessUrl;

    /**
     * 预览地址
     */
    @ApiModelProperty(name = "预览地址")
    private String previewUrl;

    /**
     * 文件展示类型
     */
    @ApiModelProperty(name = "来源类型：local-本地上传")
    private String sourceType;

    /**
     * 文件上传时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date uploadTime;

    /** 删除标识：0-正常 1-删除 */
    @ApiModelProperty(name = "删除标识：0-正常 1-删除")
    private String delFlag;

    /**
     * 上传的用户id
     */
    @ApiModelProperty(name = "上传者ID")
    private String userId;

    /**
     * 上传失败的错误信息
     */
    @ApiModelProperty(name = "上传失败的错误信息")
    private String errorMsg;

    /** 子集文件和文件夹 */
    @ApiModelProperty(name = "子集文件和文件夹")
    private List<FileInfoVO> children;

    public static FileInfoVO build(MultipartFile file) {
        // 判断文件是否为空
        if (file.isEmpty()) {
            throw new MyException("文件不能为空");
        }
        // 判断文件后缀名是否合法
        int dotPos = file.getOriginalFilename().lastIndexOf(".");
        if (dotPos < 0) {
            throw new MyException("文件名称不合法");
        }
        // 获取文件大小
        Long size = file.getSize();
        // 源文件名(带.号)
        String originalFilename = file.getOriginalFilename();
        // 文件后缀名(文件类型)
        String fileExt = FileUtil.getFileExtension(originalFilename);
        // 判断是否是合法的文件后缀
        if (!FileUtil.isFileAllowed(fileExt)) {
            throw new MyException("文件类型不符合要求");
        }
        // 文件类型
        String fileType;
        if (FileUtil.isCodeFile(fileExt)) {
            fileType = "codeFile";
        } else if (FileUtil.isImgFile(fileExt)) {
            fileType = "imageFile";
        } else if (FileUtil.isNormalOfficeFile(fileExt)) {
            fileType = "normalOfficeFile";
        } else {
            fileType = fileExt;
        }
        // 生成新的文件名
        String uuid = UUID.fastUUID().toString(true);
        String fileSysName = uuid + "." + fileExt;
        FileInfoVO fileInfoVo = new FileInfoVO();
        fileInfoVo.setId(uuid);
        fileInfoVo.setFileType(fileExt);
        fileInfoVo.setFileSize(size);
        fileInfoVo.setOriginalName(originalFilename);
        fileInfoVo.setFileSysName(fileSysName);
        fileInfoVo.setShowName(originalFilename);
        fileInfoVo.setDirFlag(0);
        fileInfoVo.setUploadTime(new Date());
        fileInfoVo.setFileType(fileType);
        fileInfoVo.setFileExt(fileExt);
        fileInfoVo.setSourceType("local");
        return fileInfoVo;
    }

    public FileInfo buildFileInfo() {
        return FileInfo.builder()
                .id(id)
                .parentId(parentId)
                .bucketName(bucketName)
                .originalName(originalName)
                .fileSysName(fileSysName)
                .showName(showName)
                .fileExt(fileExt)
                .fileType(fileType)
                .fileSize(fileSize)
                .fileMd5(fileMd5)
                .dirFlag(dirFlag)
                .filePath(FileUtil.sopPath(filePath))
                .secretKey(secretKey)
                .accessUrl(accessUrl)
                .sourceType(sourceType)
                .createTime(uploadTime)
                .createId(userId)
                .build();
    }
}
